package com.rizzo.analytics.services.ctx;

import com.rizzo.analytics.services.init.LocalDBInitializer;
import com.rizzo.infrastructure.amqp.rabbit.log4j.LogStatement;
import com.rizzo.infrastructure.performance.redis.LoggingPerformanceMonitor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaDialect;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaDialect;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

@Configuration
@EnableJpaRepositories("com.rizzo.analytics.services.repo")
@EnableTransactionManagement
public class ApplicationConfig implements InitializingBean {

    @Autowired
    private DataSource dataSource;

    @Autowired
    private Database database;

// TODO if we want to initialize the DB with scripts
//    @Bean
//    public DataSourceInitializer dataSourceInitializer() {
//        DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
//        dataSourceInitializer.setDataSource(dataSource());
//        ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
//        databasePopulator.setScripts(new ClassPathResource[]{new ClassPathResource()});
//        dataSourceInitializer.setDatabasePopulator(databasePopulator);
//        dataSourceInitializer.afterPropertiesSet();
//        return dataSourceInitializer;
//    }

    @Bean
    @DependsOn("dataSource")
    public EntityManagerFactory entityManagerFactory() {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setDatabase(database);
        vendorAdapter.setGenerateDdl(true);
        vendorAdapter.setShowSql(true);
        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setJpaDialect(jpaDialect());
        factory.setJpaVendorAdapter(vendorAdapter);
        factory.setPackagesToScan(getClass().getPackage().getName(), "com.rizzo.analytics.domain");
        factory.setDataSource(dataSource);
        factory.afterPropertiesSet();
        return factory.getObject();
    }

    @Bean
    public JpaDialect jpaDialect() {
        return new HibernateJpaDialect();
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager txManager = new JpaTransactionManager();
        txManager.setEntityManagerFactory(entityManagerFactory());
        return txManager;
    }

    @Bean(name = "loggingPerformanceMonitor")
    public LoggingPerformanceMonitor loggingPerformanceMonitor() {
        LoggingPerformanceMonitor loggingPerformanceMonitor = new LoggingPerformanceMonitor();
        loggingPerformanceMonitor.setPrefix(LogStatement.PERFORMANCE_PREFIX);
        loggingPerformanceMonitor.setUseDynamicLogger(true);
        return loggingPerformanceMonitor;
    }

    @Bean(name = "localDBInitializer")
    public LocalDBInitializer localDBInitializer() {
        return new LocalDBInitializer();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        localDBInitializer().createStandardAccounts();
    }

}
